package com.gitee.kamismile.stoneComEx.common.persist.base;

import com.gitee.kamismile.stone.commmon.base.pagination.PaginationData;
import com.gitee.kamismile.stone.commmon.base.pagination.PaginationInfo;
import com.gitee.kamismile.stone.commmon.util.ValueUtils;
import com.gitee.kamismile.stoneComEx.common.Constant;
import com.gitee.kamismile.stoneComEx.common.persist.support.PageableDAO;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.util.Assert;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public abstract class AbstractBaseMapperDAO<T, K> extends AbstractBaseMapper implements IBaseDAO<T, K> {

	protected final Logger log =LoggerFactory.getLogger(getClass());
	private SqlSessionTemplate sqlSessionTemplate;

	public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
		this.sqlSessionTemplate = sqlSessionTemplate;
	}

	private PageableDAO pageableDAO;
	private ISqlMapper<T, K> mapper;

	public AbstractBaseMapperDAO() {

	}

	public AbstractBaseMapperDAO(SqlSessionTemplate sqlSessionTemplate) {
		this.sqlSessionTemplate = sqlSessionTemplate;
		pageableDAO = new PageableDAO(getSqlSessionTemplate());
		if(null!=getMapperClass())
		mapper = getSqlSessionTemplate().getMapper(getMapperClass());
	}

	public final SqlSessionTemplate getSqlSessionTemplate() {
		return sqlSessionTemplate;
	}

	protected final ISqlMapper<T, K> getSqlMapper() {
		return mapper;
	}

	protected String getClassName(@SuppressWarnings("rawtypes") Class clazz) {
		return clazz.getName();
	}

	@Override
	public int countByCriteria(IModelExample example) {
		return getSqlMapper().countByExample(example);
	}

	@Override
	public int add(T record) {
		Assert.notNull(record, "AbstractBaseMapperDAO.add(record) : 传入的record参数不能为null.");
		int count = getSqlSessionTemplate().insert(getFullMapperId(MapperIdType.Insert), record);
		return handleCount(count);
	}

	@Override
	public int addSelective(T record) {
		Assert.notNull(record, "AbstractBaseMapperDAO.addSelective(record) : 传入的record参数不能为null.");
		int count = getSqlSessionTemplate().insert(getFullMapperId(MapperIdType.InsertSelective), record);
		return handleCount(count);
	}

	@Override
	public List<T> getListByCriteria(IModelExample example) {
		final List<T> results = getSqlSessionTemplate().selectList(getFullMapperId(MapperIdType.SelectByExample), example);
		if (results == null || results.size() == 0) {
			return Collections.emptyList();
		}
		log.debug(results.size() + "条记录符合条件.");
		return results;
	}

	@Override
	public List<Map<String,Object>> getListByMap(String statement,Object parameter) {
		List<Map<String,Object>> results = getSqlSessionTemplate().selectList(statement, parameter);
		if (results == null || results.size() == 0) {
			return Collections.emptyList();
		}
		log.debug(results.size() + "条记录符合条件.");
		return results;
	}

	@SuppressWarnings("unchecked")
	@Override
	public T getByPrimaryKey(K id) {
		return (T) getSqlSessionTemplate().selectOne(getFullMapperId(MapperIdType.SelectByPrimaryKey), id);
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public int editByCriteriaSelective(T record, IModelExample example) {
		Assert.notNull(record, "AbstractBaseMapperDAO.editByCriteriaSelective(record,example) : 传入的record参数不能为null.");
		final Map map = new HashMap();
		map.put("record", record);
		if (example != null) {
			map.put("example", example);
		}
		return handleEdit(MapperIdType.UpdateByExampleSelective, map);
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public int editByCriteria(T record, IModelExample example) {
		Assert.notNull(record, "AbstractBaseMapperDAO.editByCriteria(record, example) : 传入的record参数不能为null.");
		final Map map = new HashMap();
		map.put("record", record);
		if (example != null) {
			map.put("example", example);
		}
		return handleEdit(MapperIdType.UpdateByExample, map);
	}

	@Override
	public int editByPrimaryKeySelective(T record) {
		Assert.notNull(record, "AbstractBaseMapperDAO.editByPrimaryKeySelective(record) : 传入的参数不能为null.");
		return handleEdit(MapperIdType.UpdateByPrimaryKeySelective, record);
	}

	@Override
	public int editByPrimaryKey(T record) {
		Assert.notNull(record, "AbstractBaseMapperDAO.editByPrimaryKey(record) : 传入的参数不能为null.");
		return handleEdit(MapperIdType.UpdateByPrimaryKey, record);
	}

	protected int handleCount(int count) {
		return count;
	}

	private int handleEdit(MapperIdType editStatement, Object param) {
		int count = getSqlSessionTemplate().update(getFullMapperId(editStatement), param);
		return handleCount(count);
	}

	private int handleEdit(String editStatement, Object param) {
		int count = getSqlSessionTemplate().update(getFullMapperId(editStatement), param);
		return handleCount(count);
	}



	@Override
	public PaginationData<T> getByCriteria(final IModelExample example, final int pageId, final int pageSize) {
		return getByCriteriaForInner(example, pageId, pageSize);
	}

	protected final PaginationData<T> getByCriteriaForInner(final IModelExample example, final int pageId,
			final int pageSize) {
		// 总记录条数
		final int totalCount = countByCriteria(example);
		// no data found
		if (totalCount == 0) {
			return new PaginationData<T>(Collections.<T> emptyList(), 1, pageableDAO.getLimit(pageSize), 0, 0);
		}
		// 每页显示条数
		final int limit = pageableDAO.getLimit(pageSize);
		// 总页数
		final int totalPages = (int) Math.ceil(totalCount * 1.0 / limit);
		// 当前页码
		final int curPageId = pageableDAO.getCurPageId(pageId, totalPages);
		// 偏移量:当前页的第一条记录的前一个位置
		final int offset = pageableDAO.getOffset(curPageId, limit);
		// 当前页应包含的数据
		final List<T> list = getSqlSessionTemplate().selectList(getFullMapperId(MapperIdType.SelectByExample), example,
				new RowBounds(offset, limit));

		final PaginationData<T> data = new PaginationData<T>(list, curPageId, limit, totalPages, totalCount);

		return data;
	}

	public  PaginationData<T> getByMapForInner(final String sel,final Map map, final int pageId,
			final int pageSize) {
		// 总记录条数
		final int totalCount = getSqlSessionTemplate().selectOne(getFullMapperId("countBy"+sel), map);
		// no data found
		if (totalCount == 0) {
			return new PaginationData<T>(Collections.<T> emptyList(), 1, pageableDAO.getLimit(pageSize), 0, 0);
		}
		// 每页显示条数
		final int limit = pageableDAO.getLimit(pageSize);
		// 总页数
		final int totalPages = (int) Math.ceil(totalCount * 1.0 / limit);
		// 当前页码
		final int curPageId = pageableDAO.getCurPageId(pageId, totalPages);
		// 偏移量:当前页的第一条记录的前一个位置
		final int offset = pageableDAO.getOffset(curPageId, limit);
		// 当前页应包含的数据
		final List<T> list = getSqlSessionTemplate().selectList(getFullMapperId(sel), map,
				new RowBounds(offset, limit));

		final PaginationData<T> data = new PaginationData<T>(list, curPageId, limit, totalPages, totalCount);

		return data;
	}



	@Override
	public PaginationData<T> getByCriteria(IModelExample example, int pageId) {
		return getByCriteriaForInner(example, pageId, PaginationInfo.DEFAULT_PAGE_SIZE);
	}



	@Override
	public int deleteByPrimaryKey(K id) {
		return getSqlSessionTemplate().delete(getFullMapperId(MapperIdType.DeleteByPrimaryKey), id);
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public int deleteByExample(IModelExample example) {
		return getSqlSessionTemplate().delete(getFullMapperId(MapperIdType.DeleteByExample), example);
	}


	@Override
	public int updateOrAdd(T record, K id) {
		//先查询是否存在
		T obj = getByPrimaryKey(id);
		//添加
		if(null == obj){
			return this.addSelective(record);
		}
		//修改
		else{
			return this.editByPrimaryKeySelective(record);
		}
	}

	@Override
	public int checkWithAdd(T record, K id) {
		//先查询是否存在
		T obj = getByPrimaryKey(id);
		//添加
		if(null == obj){
			return this.addSelective(record);
		}
		return 0;
	}

	public final <E> PaginationData<E> getByMap(final String count, final String select, Map<String, Object> params,
			int pageId, int pageSize) {
		return pageableDAO.getByMap(count, select, params, pageId, pageSize);
	}



	@SuppressWarnings("unchecked")
	@Override
	public T getModelByCriteria(IModelExample example) {
		return (T)getSqlSessionTemplate().selectOne(getFullMapperId(MapperIdType.SelectByExample), example);
	}

	protected int getPageNum(Map<String,Object> params){
		return ValueUtils.isIntegerNull(params.get(Constant.PAGE_NUM), Constant.DEFAULT_PAGE_NUM);
	}

	protected int getPageSize(Map<String,Object> params){
		return ValueUtils.isIntegerNull(params.get(Constant.PAGE_SIZE),Constant.DEFAULT_PAGE_SIZE);
	}

	protected PaginationData<Map<String, Object>> queryStatisticsPage(Map<String, Object> params,String statement) {
		PaginationData<Map<String,Object>> data = getByMap(null, getMapperClass().getName() + "." + statement ,
				params, getPageNum(params), getPageSize(params));
		return data;
	}

	@Override
	public List<T> queryListByMap(String statement, Object map) {
		List<T> results = getSqlSessionTemplate().selectList(statement, map);
		if (results == null || results.size() == 0) {
			return Collections.emptyList();
		}
		log.debug(results.size() + "条记录符合条件.");
		return results;
	}

	public int deleteBySql(String statement,Map map) {
		return getSqlSessionTemplate().delete(getFullMapperId(statement), map);
	}

	public int deleteBySql(String statement) {
		return getSqlSessionTemplate().delete(getFullMapperId(statement));
	}

	public int updateBySql(String statement,Map map) {
		return getSqlSessionTemplate().update(getFullMapperId(statement), map);
	}

	public PageableDAO getPageableDAO() {
		return pageableDAO;
	}
}
